package com.fdb.efp.console.api.rest;

import com.fdb.basic.framework.core.constant.ApplicationConstance;
import com.fdb.basic.framework.core.constant.DataRuleType;
import com.fdb.basic.framework.core.constant.ResponseData;
import com.fdb.basic.framework.core.exception.FlowException;
import com.fdb.basic.framework.core.log.LogManager;
import com.fdb.basic.framework.core.util.BeanUtility;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.core.vo.*;
import com.fdb.basic.framework.web.controller.IController;
import com.fdb.efp.console.service.facade.PrdInfoService;
import com.fdb.efp.console.service.facade.VwUserDutyService;
import com.fdb.efp.console.service.vo.PrdInfoVO;
import com.fdb.efp.console.service.vo.PrdParamVO;
import com.fdb.efp.console.service.vo.VwUserDutyVO;
import com.fdb.efp.console.service.facade.SRoleDataRuleService;
import com.fdb.efp.console.common.constance.FlowConstance;
import com.fdb.efp.console.common.util.EngineUtil;
import com.fdb.efp.console.common.vo.*;
import com.fdb.efp.console.enumeration.BizSequenceType;
import com.fdb.efp.console.executor.util.AbstractController;
import com.fdb.efp.console.service.FlowEngine;
import com.fdb.efp.console.service.facade.*;
import com.fdb.efp.console.service.vo.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 业务流转中心对外提供的API
 *
 * @author Cytus_
 * @version 1.0
 * @since 2018年5月11日 上午9:10:08
 */
@RestController
@RequestMapping("/api")
public class FlowController extends AbstractController implements IController {

    private static Logger logger = LoggerFactory.getLogger(FlowController.class);

    @Autowired
    @Qualifier("bizFlowEngine")
    private FlowEngine bizFlowEngine;

    @Autowired
    @Qualifier("prdInfoService")
    private PrdInfoService prdInfoService;


    @Autowired
    @Qualifier("bizFlowEngineInquireService")
    private BizFlowEngineInquireService bizFlowEngineInquireService;

    @Autowired
    @Qualifier("instFlowTaskService")
    private InstFlowTaskService instFlowTaskService;

    @Autowired
    @Qualifier("instFlowParamService")
    private InstFlowParamService instFlowParamService;

    @Autowired
    @Qualifier("bizFlowTaskParamService")
    private BizFlowTaskParamService bizFlowTaskParamService;

	/*@Autowired
	private SequenceService sequenceService;*/

    @Autowired
    @Qualifier("instFlowProcessService")
    private InstFlowProcessService instFlowProcessService;
    @Autowired
    @Qualifier("sRoleDataRuleService")
    private SRoleDataRuleService sRoleDataRuleService;

    @Autowired
    @Qualifier("vwUserDutyService")
    private VwUserDutyService vwUserDutyService;

    @Autowired
    @Qualifier("instFlowHistoryService")
    private InstFlowHistoryService instFlowHistoryService;

    /**
     * 启动流程
     *
     * @return
     * @throws FlowException
     */
    @RequestMapping(value = "/init", method = RequestMethod.GET)
    public @ResponseBody
    ResponseData<String> initflow(@RequestParam("flowId") String flowId, @RequestParam("bizLegalOrgCode") String bizLegalOrgCode) throws FlowException {
        ResponseData<String> responseData = new ResponseData<String>();
        try {
            String flowInstId = bizFlowEngine.initBizFlow(flowId, bizLegalOrgCode);
            responseData.createData(flowInstId, ApplicationConstance.SUCCESS, ApplicationConstance.SUCCESS_MESSAGE, true);
        } catch (Exception e) {
            logger.error("实例化流程ID:" + flowId + "出现异常!", e);
            responseData.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
        }
        return responseData;
    }


    /**
     * 异步启动事件
     *
     * @return
     * @throws FlowException
     */
    @RequestMapping(value = "/event/start/async", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<String> asyncStartEvent(@RequestBody PageSubmitRequestVO requestVo) throws FlowException {
        ResponseData<String> responseData = new ResponseData<String>();
        try {
            // 业务法人机构 TODO
            // assertBizLegalOrgCode(requestVo.getBizLegalOrgCode());
            // 流程ID
            String flowId = reGetFlowId(requestVo.getPrdId(), requestVo.getFlowId());
            // 事件流水号
            String bizSerno = requestVo.getE_bizSerno();
            if (StringUtil.isEmpty(bizSerno)) {
                bizSerno = getBizSernoSequence(requestVo.getScene(), requestVo.getPrdId());
            }
            if (StringUtil.isEmpty(requestVo.getG_bizSerno())) {
                requestVo.setG_bizSerno(bizSerno);
            }
            bizSerno = (String) bizFlowEngine.startEvent(flowId, requestVo.getEventId(),
                    requestVo.getG_bizSerno(), bizSerno, requestVo.getBizLegalOrgCode(), requestVo.getData(), false);
            responseData.createData(bizSerno, ApplicationConstance.SUCCESS, ApplicationConstance.SUCCESS_MESSAGE, true);
        } catch (Exception e) {
            logger.error("事件实例ID:" + requestVo.getE_bizSerno() + ", 事件ID:" + requestVo.getEventId() + "继续执行流程出现异常!", e);
            responseData.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
        }
        return responseData;
    }

    /**
     * 同步启动事件
     *
     * @return
     * @throws FlowException
     */
    @RequestMapping(value = "/event/start/sync", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<Object> syncStartEvent(@RequestBody PageSubmitRequestVO requestVo) throws FlowException {
        ResponseData<Object> responseData = new ResponseData<Object>();
        try {
            //assertBizLegalOrgCode(requestVo.getBizLegalOrgCode());
            String flowId = reGetFlowId(requestVo.getPrdId(), requestVo.getFlowId());
            String bizSerno = requestVo.getE_bizSerno();
            if (StringUtil.isEmpty(bizSerno)) {
                bizSerno = getBizSernoSequence(requestVo.getScene(), requestVo.getPrdId());
            }
            if (StringUtil.isEmpty(requestVo.getG_bizSerno())) {
                requestVo.setG_bizSerno(bizSerno);
            }
            Object rtnObj = bizFlowEngine.startEvent(flowId, requestVo.getEventId(),
                    requestVo.getG_bizSerno(), bizSerno, requestVo.getBizLegalOrgCode(), requestVo.getData(), true);
            responseData.createData(rtnObj, ApplicationConstance.SUCCESS, ApplicationConstance.SUCCESS_MESSAGE, true);
        } catch (Exception e) {
            logger.error("事件实例ID:" + requestVo.getE_bizSerno() + ", 事件ID:" + requestVo.getEventId() + "继续执行流程出现异常!", e);
            responseData.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
        }
        return responseData;
    }


    /**
     * 继续当前事件
     *
     * @return
     * @throws FlowException
     */
    @RequestMapping(value = "/event/continue/page/async", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<String> asyncContinueEvent(@RequestBody PageSubmitRequestVO requestVo) throws FlowException {
        ResponseData<String> responseData = new ResponseData<String>();
        try {

            InstFlowProcessVO process = instFlowProcessService.queryByNodeInstanceId(requestVo.getInstNodeId());
            if (Objects.nonNull(process)
                    && !(FlowConstance.NODE_STATUS_PAUSE.equals(process.getInstNodeState()) || FlowConstance.NODE_STATUS_EXCEPTION.equals(process.getInstNodeState()))) {
                responseData.createData("2", ApplicationConstance.SUCCESS, ApplicationConstance.SUCCESS_MESSAGE, true);
            } else {
                Object object = requestVo.getData();
                PageApproveVO aprv = requestVo.getAprv();
                bizFlowEngine.continueEvent(requestVo.getG_bizSerno(),
                        requestVo.getE_bizSerno(), requestVo.getEventId(), aprv, object, false);
                responseData.createData("1", ApplicationConstance.SUCCESS, ApplicationConstance.SUCCESS_MESSAGE, true);
            }
        } catch (Exception e) {
            logger.error("事件实例ID:" + requestVo.getE_bizSerno() + ", 事件ID:" + requestVo.getEventId() + "继续执行流程出现异常!", e);
            responseData.createData("0", ApplicationConstance.FAILURE, e.getMessage(), false);
        }
        return responseData;
    }

    /**
     * 继续当前事件
     *
     * @return
     * @throws FlowException
     */
    @RequestMapping(value = "/event/continue/page/sync", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<Object> syncContinueEvent(@RequestBody PageSubmitRequestVO requestVo) throws FlowException {
        ResponseData<Object> responseData = new ResponseData<Object>();
        try {
            InstFlowProcessVO process = instFlowProcessService.queryByNodeInstanceId(requestVo.getInstNodeId());
            if (Objects.nonNull(process)
                    && !(FlowConstance.NODE_STATUS_PAUSE.equals(process.getInstNodeState()) || FlowConstance.NODE_STATUS_EXCEPTION.equals(process.getInstNodeState()))) {
                responseData.createData(null, ApplicationConstance.SUCCESS, ApplicationConstance.SUCCESS_MESSAGE, true);
            } else {
                Object object = requestVo.getData();
                Object rtnObj = bizFlowEngine.continueEvent(requestVo.getG_bizSerno(), requestVo.getE_bizSerno(),
                        requestVo.getEventId(), null, object, true);
                responseData.createData(rtnObj, ApplicationConstance.SUCCESS, ApplicationConstance.SUCCESS_MESSAGE, true);
            }
        } catch (Exception e) {
            logger.error("事件实例ID:" + requestVo.getE_bizSerno() + ", 事件ID:" + requestVo.getEventId() + "继续执行流程出现异常!", e);
            responseData.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
        }
        return responseData;
    }


    /**
     * restful同步启动
     *
     * @param httpRequestVo
     * @return
     */
    @RequestMapping(value = "/event/start/restful/sync", method = RequestMethod.POST)
    public @ResponseBody
    EngineHttpResponseVO restfulSyncStartEvent(@RequestBody EngineHttpRequestVO httpRequestVo) {
        EngineHttpResponseVO httpResponseVo = new EngineHttpResponseVO();
        try {
            assertBizLegalOrgCode(httpRequestVo.getBizLagelOrgCode());
            String bizSerno = httpRequestVo.getE_bizSerno();
            if (StringUtil.isEmpty(bizSerno)) {
                bizSerno = getBizSernoSequence(httpRequestVo.getScene(), httpRequestVo.getPrdId());
            }
            if (StringUtil.isEmpty(httpRequestVo.getG_bizSerno())) {
                httpRequestVo.setG_bizSerno(bizSerno);
            }
            //额度激活流程
            String flowId = reGetFlowId(httpRequestVo.getPrdId(), httpRequestVo.getFlowId());
            Object rtnObject = bizFlowEngine.startEvent(flowId, httpRequestVo.getEventId(),
                    httpRequestVo.getG_bizSerno(), bizSerno, httpRequestVo.getBizLagelOrgCode(), httpRequestVo.getData(), true);
            httpResponseVo.setData(rtnObject);
            httpResponseVo.setResult(true);
        } catch (Exception e) {
            logger.error("同步启动事件出现异常!", e);
            httpResponseVo.setErrorCode("");
            httpResponseVo.setErrorMsg(e.getMessage());
            httpResponseVo.setResult(false);
        }
        return httpResponseVo;
    }

    /**
     * restful异步步启动
     *
     * @param httpRequestVo
     * @return
     */
    @RequestMapping(value = "/event/start/restful/async", method = RequestMethod.POST)
    public @ResponseBody
    EngineHttpResponseVO restfulAsyncStartEvent(@RequestBody EngineHttpRequestVO httpRequestVo) {
        EngineHttpResponseVO httpResponseVo = new EngineHttpResponseVO();
        try {
            //assertBizLegalOrgCode(httpRequestVo.getBizLagelOrgCode());
            String bizSerno = httpRequestVo.getE_bizSerno();
            if (StringUtil.isEmpty(bizSerno)) {
                bizSerno = getBizSernoSequence(httpRequestVo.getScene(), httpRequestVo.getPrdId());
            }
            if (StringUtil.isEmpty(httpRequestVo.getG_bizSerno())) {
                httpRequestVo.setG_bizSerno(bizSerno);
            }
            String flowId = reGetFlowId(httpRequestVo.getPrdId(), httpRequestVo.getFlowId());
            Object rtnObject = bizFlowEngine.startEvent(flowId, httpRequestVo.getEventId(),
                    httpRequestVo.getG_bizSerno(), bizSerno, httpRequestVo.getBizLagelOrgCode(), httpRequestVo.getData(), false);
            httpResponseVo.setData(rtnObject);
            httpResponseVo.setResult(true);
        } catch (Exception e) {
            logger.error("同步启动事件出现异常!", e);
            httpResponseVo.setErrorCode("");
            httpResponseVo.setErrorMsg(e.getMessage());
            httpResponseVo.setResult(false);
        }
        return httpResponseVo;
    }

    /**
     * restful 异步继续当前流转信息
     *
     * @param httpRequestVo
     * @return
     */
    @RequestMapping(value = "/event/continue/restful/async", method = RequestMethod.POST)
    public @ResponseBody
    EngineHttpResponseVO restfulAsyncContinueEvent(@RequestBody EngineHttpRequestVO httpRequestVo) {
        EngineHttpResponseVO httpResponseVo = new EngineHttpResponseVO();
        try {
            bizFlowEngine.continueEvent(httpRequestVo.getG_bizSerno(),
                    httpRequestVo.getE_bizSerno(), httpRequestVo.getEventId(), null, httpRequestVo.getData(), false);
            httpResponseVo.setData(ApplicationConstance.SUCCESS);
            httpResponseVo.setResult(true);
        } catch (Exception e) {
            logger.error("异步继续动事件出现异常!", e);
            httpResponseVo.setErrorCode(ApplicationConstance.FAILURE);
            httpResponseVo.setErrorMsg(e.getMessage());
            httpResponseVo.setResult(false);
        }
        return httpResponseVo;
    }

    /**
     * restful 同步继续当前流转信息
     *
     * @param httpRequestVo
     * @return
     */
    @RequestMapping(value = "/event/continue/restful/sync", method = RequestMethod.POST)
    public @ResponseBody
    EngineHttpResponseVO restfulSyncContinueEvent(@RequestBody EngineHttpRequestVO httpRequestVo) {
        EngineHttpResponseVO httpResponseVo = new EngineHttpResponseVO();
        try {
            Object rtnObj = bizFlowEngine.continueEvent(httpRequestVo.getG_bizSerno(),
                    httpRequestVo.getE_bizSerno(), httpRequestVo.getEventId(), null, httpRequestVo.getData(), true);
            httpResponseVo.setData(rtnObj);
            httpResponseVo.setResult(true);
        } catch (Exception e) {
            logger.error("同步继续动事件出现异常!", e);
            httpResponseVo.setErrorCode(ApplicationConstance.FAILURE);
            httpResponseVo.setErrorMsg(e.getMessage());
            httpResponseVo.setResult(false);
        }
        return httpResponseVo;
    }


    /**
     * 审批信息查询
     *
     * @param instNodeId
     * @return
     */
    @RequestMapping(value = "/node/aprv", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<PageApproveShowVO> queryPageAprvInfo(@RequestBody PageInquireInVO inVo) {
        PageApproveShowVO vo = new PageApproveShowVO();

        InstFlowProcessVO process = instFlowProcessService.queryByNodeInstanceId(inVo.getInstNodeId());
        if (Objects.nonNull(process)
                && !(FlowConstance.NODE_STATUS_PAUSE.equals(process.getInstNodeState()) || FlowConstance.NODE_STATUS_EXCEPTION.equals(process.getInstNodeState()))) {
            vo.setDealFlag("2");
        } else {
            LogManager.info(inVo.getBizSerno() + "-" + inVo.getInstNodeId(), instFlowProcessService, "queryByNodeInstanceId");
            InstFlowProcessVO processVo = instFlowProcessService.queryByNodeInstanceId(inVo.getInstNodeId());

            vo.setBizNodeId(processVo.getBizNodeId());
            vo.setBizNodeName(processVo.getBizNodeName());
            vo.setBizNodeType(processVo.getBizNodeType());
            vo.setInstNodeId(processVo.getInstNodeId());
            vo.setBizSerno(processVo.getBizSerno());
            vo.setG_bizSerno(inVo.getInstFlowId());
            vo.setEventId(inVo.getEventId());

            LogManager.info(inVo.getBizSerno() + "-" + inVo.getInstNodeId(), instFlowTaskService, "queryPageShowPluginTaskInfoByInstNodeId");
            List<InstFlowTaskVO> tasks = instFlowTaskService.queryPageShowPluginTaskInfoByInstNodeId(inVo.getInstNodeId());

            String pauseTaskId = null;
            InstFlowTaskVO pauseTask = tasks.parallelStream().filter(s -> FlowConstance.TASK_STATUS_PAUSE.equals(s.getTaskState())).findFirst().orElse(null);
            if (Objects.nonNull(pauseTask)) {
                pauseTaskId = pauseTask.getTaskId();
            }

            InstFlowParamVO paramVo = new InstFlowParamVO();
            paramVo.setBizSerno(inVo.getBizSerno());
            paramVo.setInstNodeId(inVo.getInstNodeId());
            paramVo.setTaskId(pauseTaskId);

            LogManager.info(inVo.getBizSerno() + "-" + inVo.getInstNodeId(), instFlowParamService, "queryContent");
            InstFlowParamVO param = instFlowParamService.queryContent(paramVo);

            try {
                PluginVO pluginVo = EngineUtil.deserializePluginVo(param.getBizParamContent());

                for (InstFlowTaskVO task : tasks) {
                    PagePluginVO pageVo = BeanUtility.beanCopy(task, new PagePluginVO());

                    LogManager.info(inVo.getBizSerno() + "-" + inVo.getInstNodeId() + "-" + task.getTaskId(), bizFlowTaskParamService, "queryTaskParamsByTaskId");
                    List<BizFlowTaskParamVO> taskParams = bizFlowTaskParamService.queryTaskParamsByTaskId(task.getTaskId());
                    if (Objects.nonNull(taskParams) && !taskParams.isEmpty()) {
                        List<BizFlowTaskParamVO> pageInParams = taskParams.parallelStream().filter(s -> FlowConstance.PLUGIN_IN_PARAM.equals(s.getBizParamIo())).collect(Collectors.toList());

                        for (int i = 0; i < pageInParams.size(); i++) {
                            BizFlowTaskParamVO paramInVo = pageInParams.get(i);
                            if (FlowInVO.class.getName().equals(paramInVo.getParamClass())) {
                                pageVo.addData(paramInVo.getBizTargetParamCode(), pluginVo.getFlowInVo());
                            } else {
                                if (pluginVo.getVo(paramInVo.getBizTargetParamCode()) == null) {
                                    pageVo.addData(paramInVo.getBizTargetParamCode(), pluginVo.getVo(FlowConstance.PAGE_PLUGIN_VO_KEY));

                                } else {
                                    pageVo.addData(paramInVo.getBizTargetParamCode(), pluginVo.getVo(paramInVo.getBizTargetParamCode()));
                                }

                            }
                            pageVo.setDataKey(paramInVo.getBizTargetParamCode());
                        }
                    }

                    vo.addVo(pageVo);
                }
                vo.setDealFlag("1");
            } catch (Exception e) {
                logger.error("获得审批信息出现异常!", e);
                vo.setDealFlag("0");
            }
        }
        return getResponseData(vo);
    }

    /**
     * 审批信息查询
     *
     * @param instNodeId
     * @return
     */
    @RequestMapping(value = "/node/aprv/finish", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<PageApproveShowVO> queryFinishPageAprvInfo(@RequestBody PageInquireInVO inVo) {
        PageApproveShowVO vo = new PageApproveShowVO();
        LogManager.info(inVo.getBizSerno() + "-" + inVo.getInstNodeId(), instFlowProcessService, "queryByNodeInstanceId");
        InstFlowProcessVO processVo = instFlowProcessService.queryByNodeInstanceId(inVo.getInstNodeId());

        vo.setBizNodeId(processVo.getBizNodeId());
        vo.setBizNodeName(processVo.getBizNodeName());
        vo.setBizNodeType(processVo.getBizNodeType());
        vo.setInstNodeId(processVo.getInstNodeId());
        vo.setBizSerno(processVo.getBizSerno());
        vo.setG_bizSerno(inVo.getInstFlowId());
        vo.setEventId(inVo.getEventId());

        LogManager.info(inVo.getBizSerno() + "-" + inVo.getInstNodeId(), instFlowTaskService, "queryPageShowPluginTaskInfoByInstNodeId");
        List<InstFlowTaskVO> tasks = instFlowTaskService.queryByInstNodeId(inVo.getInstNodeId());


        InstFlowParamVO paramVo = new InstFlowParamVO();
        paramVo.setBizSerno(inVo.getBizSerno());

        LogManager.info(inVo.getBizSerno() + "-" + inVo.getInstNodeId(), instFlowParamService, "queryContent");
        InstFlowParamVO param = instFlowParamService.queryContent(paramVo);

        try {
            PluginVO pluginVo = EngineUtil.deserializePluginVo(param.getBizParamContent());

            for (InstFlowTaskVO task : tasks) {
                PagePluginVO pageVo = BeanUtility.beanCopy(task, new PagePluginVO());

                LogManager.info(inVo.getBizSerno() + "-" + inVo.getInstNodeId() + "-" + task.getTaskId(), bizFlowTaskParamService, "queryTaskParamsByTaskId");
                List<BizFlowTaskParamVO> taskParams = bizFlowTaskParamService.queryTaskParamsByTaskId(task.getTaskId());
                if (Objects.nonNull(taskParams) && !taskParams.isEmpty()) {
                    List<BizFlowTaskParamVO> pageInParams = taskParams.parallelStream().filter(s -> FlowConstance.PLUGIN_IN_PARAM.equals(s.getBizParamIo())).collect(Collectors.toList());

                    for (int i = 0; i < pageInParams.size(); i++) {
                        BizFlowTaskParamVO paramInVo = pageInParams.get(i);
                        if (FlowInVO.class.getName().equals(paramInVo.getParamClass())) {
                            pageVo.addData(paramInVo.getBizTargetParamCode(), pluginVo.getFlowInVo());
                        } else {
                            if (pluginVo.getVo(paramInVo.getBizTargetParamCode()) == null) {
                                pageVo.addData(paramInVo.getBizTargetParamCode(), pluginVo.getVo(FlowConstance.PAGE_PLUGIN_VO_KEY));

                            } else {
                                pageVo.addData(paramInVo.getBizTargetParamCode(), pluginVo.getVo(paramInVo.getBizTargetParamCode()));
                            }
                        }
                        pageVo.setDataKey(paramInVo.getBizTargetParamCode());
                    }
                }

                vo.addVo(pageVo);
            }

        } catch (Exception e) {
            logger.error("获得审批信息出现异常!", e);
        }

        return getResponseData(vo);
    }


    /**
     * 查询待办事项
     *
     * @param vo
     * @return
     */
    @RequestMapping(value = "/done/wait", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<List<PageInquireOutVO>> waitDone(@RequestBody PageInquireInVO vo) {
        List<PageInquireOutVO> outputVo = null;
        // 根据用户角色获取用户权限方案
        //Map<String,String> dataRuleTypeMap = sRoleDataRuleService.getDataRuleType(httpRequest.getRequestURI(), getUserRoles());
        //vo.setPrdCodebyBaseInfo(dataRuleTypeMap == null ? null:dataRuleTypeMap.get(PubConstant.PRD_CODE));
        //DataRuleType dataRuleType = DataRuleType.getDataRuleType(dataRuleTypeMap == null ? null:dataRuleTypeMap.get(PubConstant.PERMIS_TYPE));
        DataRuleType dataRuleType = DataRuleType.getDataRuleType("01");
        setUserInfoToVO(vo);
        //vo.setDutyCodeStr("'"+vo.getDutyCodeStr()+"'");
        // 根据权限方案调用不同的方案进行数据查询
        switch (dataRuleType) {
            case Owner:
                outputVo = bizFlowEngineInquireService.waitDoneOwner(vo);
                break;
            case CurrOrg:
                outputVo = bizFlowEngineInquireService.waitDoneCurrOrg(vo);
                break;
            case CurrDownOrg:
                outputVo = bizFlowEngineInquireService.waitDoneCurrDownOrg(vo);
                break;
            default:
                outputVo = bizFlowEngineInquireService.waitDoneOwner(vo);
                break;
        }
        return getResponseData(outputVo);
    }

    /**
     * 查询首页的待办事项
     *
     * @param vo
     * @return
     */
    @RequestMapping(value = "/done/wait/dashboard", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<List<DashBoardFlowVO>> waitDoneDashBoard(@RequestBody PageInquireInVO vo) {
        setUserInfoToVO(vo);
        List<DashBoardFlowVO> vos = bizFlowEngineInquireService.dashBoardFlow(vo);
        return getResponseData(vos);
    }

    /**
     * 查询已办事项
     *
     * @param vo
     * @return
     */
    @RequestMapping(value = "/done/have", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<List<PageInquireOutVO>> haveDone(@RequestBody PageInquireInVO vo) {
        // 根据用户角色获取用户权限方案
        List<PageInquireOutVO> outputVo = null;
        //Map<String,String> dataRuleTypeMap = sRoleDataRuleService.getDataRuleType(httpRequest.getRequestURI(), getUserRoles());
        //vo.setPrdCodebyBaseInfo(dataRuleTypeMap == null ? null:dataRuleTypeMap.get(PubConstant.PRD_CODE));
        //DataRuleType dataRuleType = DataRuleType.getDataRuleType(dataRuleTypeMap == null ? null:dataRuleTypeMap.get(PubConstant.PERMIS_TYPE));
        DataRuleType dataRuleType = DataRuleType.getDataRuleType("01");
        setUserInfoToVO(vo);
        // 根据权限方案调用不同的方案进行数据查询
        switch (dataRuleType) {
            case Owner:
                outputVo = bizFlowEngineInquireService.haveDoneOwner(vo);
                break;
            case CurrOrg:
                outputVo = bizFlowEngineInquireService.haveDoneCurrOrg(vo);
                break;
            case CurrDownOrg:
                outputVo = bizFlowEngineInquireService.haveDoneCurrDownOrg(vo);
                break;
            default:
                outputVo = bizFlowEngineInquireService.haveDoneOwner(vo);
                break;
        }

        return getResponseData(outputVo);
    }

    /**
     * 查询办结事项
     *
     * @param vo
     * @return
     */
    @RequestMapping(value = "/done/end", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<List<PageInquireOutVO>> endDone(@RequestBody PageInquireInVO vo) {
        // 根据用户角色获取用户权限方案
        List<PageInquireOutVO> outputVo = null;
        //Map<String, String> dataRuleTypeMap = sRoleDataRuleService.getDataRuleType(httpRequest.getRequestURI(), getUserRoles());
        //vo.setPrdCodebyBaseInfo(dataRuleTypeMap == null ? null : dataRuleTypeMap.get(PubConstant.PRD_CODE));
        //DataRuleType dataRuleType = DataRuleType.getDataRuleType(dataRuleTypeMap == null ? null : dataRuleTypeMap.get(PubConstant.PERMIS_TYPE));
        DataRuleType dataRuleType = DataRuleType.getDataRuleType("01");
        setUserInfoToVO(vo);
        // 根据权限方案调用不同的方案进行数据查询
        switch (dataRuleType) {
            case Owner:
                outputVo = bizFlowEngineInquireService.endDoneOwner(vo);
                break;
            case CurrOrg:
                outputVo = bizFlowEngineInquireService.endDoneCurrOrg(vo);
                break;
            case CurrDownOrg:
                outputVo = bizFlowEngineInquireService.endDoneCurrDownOrg(vo);
                break;
            default:
                outputVo = bizFlowEngineInquireService.endDoneOwner(vo);
                break;
        }

        return getResponseData(outputVo);
    }

    /**
     * 查询产品信息
     *
     * @param prdId
     * @return
     */
    private String queryFlowIdByPrdId(String prdId) {
        PrdParamVO paramVo = new PrdParamVO();
        paramVo.setPrdId(prdId);
        paramVo.setCrdApprFlow(true);
        LogManager.info(prdId, prdInfoService, "queryPrdInfo");
        PrdInfoVO vo = this.prdInfoService.queryPrdInfo(paramVo);
        return Objects.isNull(vo) ? null : vo.getCrdApprFlowId();
    }

    /**
     * 判断获取FLOWID 如果传入为空就从产品中获得
     *
     * @param prdId
     * @param flowId
     * @return
     * @throws FlowException
     */
    private String reGetFlowId(String prdId, String flowId) throws FlowException {
        if (StringUtil.isEmpty(flowId)) {
            flowId = queryFlowIdByPrdId(prdId);
        }
        return flowId;
    }

    /**
     * 根据场景获得seq
     *
     * @param scene
     * @param prdId
     * @return
     * @throws Exception
     */
    private String getBizSernoSequence(String scene, String prdId) throws Exception {
        String prdCode = null;
        if (StringUtil.isNotEmpty(prdId)) {
            PrdInfoVO vo = new PrdInfoVO();
            vo.setPrdId(prdId);
            LogManager.info(prdId, prdInfoService, "queryByPk");
            PrdInfoVO prdInfo = this.prdInfoService.queryByPk(vo);
            prdCode = prdInfo.getPrdCode();
        }
        String seqId = BizSequenceType.getSequenceIdByScene(scene);
        UserInfo userInfo = this.getUserInfo();
		/*if (Objects.nonNull(userInfo)) {
		    LogManager.info(prdId +"-"+ seqId, sequenceService, "getSequence");
			return this.sequenceService.getSequence(seqId, userInfo.getOrgInfo().getOrgCode(), prdCode, 
				userInfo.getLegalOrg().getOrgCode(), SequenceConstance.SEQUENCE_DEF_ORG_AREA_CODE);
		} else {
		    LogManager.info(prdId +"-"+ seqId, sequenceService, "getSequence");
			return this.sequenceService.getSequence(seqId, null, prdCode, null, SequenceConstance.SEQUENCE_DEF_ORG_AREA_CODE);
		}*/
        return "1111";
    }

    public static void assertBizLegalOrgCode(String bizLegalOrgCode) throws FlowException {
        if (StringUtil.isEmpty(bizLegalOrgCode)) {
            throw new FlowException("业务法人机构代码为空!");
        }
    }

    /**
     * 审批意见以页面插件提交
     *
     * @param vo
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/aprv/comment/submit", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<Integer> updateNodeDealComment(@RequestBody PageApproveVO vo) throws Exception {
        InstFlowProcessVO process = new InstFlowProcessVO();
        process.setInstNodeId(vo.getInstNodeId());
        process.setApproveComment(vo.getAprvComment());
        process.setApproveOpinion(vo.getAprvOpinion());
        process.setProcessState(null);
        process.setApproveTime(TimeUtil.getCurrentDateTime());
        UserInfo userInfo = this.getUserInfo();
        vo.setAprvLegalOrgCode(userInfo.getLegalOrg().getOrgCode());
        vo.setAprvOrgCode(userInfo.getOrgInfo().getOrgCode());
        vo.setAprvUserId(userInfo.getUserId());
        vo.setAprvUserName(userInfo.getUserName());
        LogManager.info(vo.getInstNodeId(), instFlowProcessService, "updateApproveInfoByNodeInstId");
        int record = instFlowProcessService.updateApproveInfoByNodeInstId(process);
        EngineVO evo = new EngineVO();
        evo = this.getPluginVoInfos(vo.getE_bizSerno(), "PageApproveVO", vo);
        this.savePluginVoInfos(evo);
        logger.info("当前节点实例:" + vo.getInstNodeId() + ", 更新审批信息结束![审批结果:" + vo.getAprvOpinion() + "]");
        return getResponseData(record);
    }

    public static void main(String[] args) throws Exception {
        PluginVO vo = EngineUtil.deserializePluginVo("CwsKB2V2ZW50SWQTSglEZW1vRW50ZXIUDAsKDHF1b3RhTGltaUFtdBMojRkUDAsKBXNlcm5vE0oUQ1JFTDIwMTkwMzI5MDAwMjM2NjcUDAsKElBBR0VfUExVR0lOX1ZPX0tFWRPSAQ1MaW5rZWRIYXNoTWFwCwtKBHBhZ2UMEygBFAwLC0oEc2l6ZQwTKAoUDAsLSgV0b3RhbAwTKBIUDAsLSgtsb2dpblVzZXJJZAwMCwtKEGxvZ2luVXNlck9yZ0NvZGUMDAsLShVsb2dpblVzZXJMZWFnZU9yZ0NvZGUMDAsLShRsb2dpblVzZXJPcmdMb2NhdGlvbgwMCwtKEXByZENvZGVieUJhc2VJbmZvDAwLC0oLZHV0eUNvZGVTdHIMDAsLSgVzZXJubwwTShRDUkVMMjAxOTAzMjkwMDAyMzY2NxQMCwtKCXF1b3RhTmFtZQwMCwtKDHF1b3RhTGltaUFtdAwTKI0ZFAwLC0oFc3RyRHQME0oKMjAxOS0wMy0wMRQMCwtKBWVuZER0DBNKCjIwMTktMDMtMjIUDAsLSgNzdHMME0oCMDAUDAsLSglxdW90YVR5cGUME0oM5a6i5oi36ZmQ6aKdFAwLC0oHY3VzVHlwZQwTSgIwMhQMCwtKCmNyZWF0ZVVzZXIME0oCMTMUDAsLSgpjcmVhdGVUaW1lDBNKEzIwMTktMDMtMjkgMTU6NDI6MTEUDAsLSgpsYXN0Q2hnVXNyDBNKD+aYpeWkqeadpeS6hu+8gRQMCwtKC2xhc3RDaGdUaW1lDBNKEzIwMTktMDktMTAgMTk6MzM6NTcUDAsLSgdldmVudElkDBNKCURlbW9FbnRlchQMCwtKCmFwcGx5U3RhdGUME0oDMTAxFAwLC0oJYXBwbHlEYXRlDBNKCjIwMTktMDctMTQUDBQMCwoKZ19iaXpTZXJubxNKFENSRUwyMDE5MDMyOTAwMDIzNjY3FAwLCgphcHBseVN0YXRlE0oDMTAxFAwLCgVlbmREdBNKCjIwMTktMDMtMjIUDAsKCmxhc3RDaGdVc3ITSg/mmKXlpKnmnaXkuobvvIEUDAsKBXN0ckR0E0oKMjAxOS0wMy0wMRQMCwoNUGFnZUFwcHJvdmVWTxP6By5jb20uaXJkc3R1ZGlvLmVmcC5mbG93LmNvbW1vbi52by5QYWdlQXBwcm92ZVZPFAwLCglxdW90YVR5cGUTSgzlrqLmiLfpmZDpop0UDAsKBXRvdGFsEygSFAwLCgNzdHMTSgIwMBQMCwoEc2l6ZRMoChQMCwoKY3JlYXRlVGltZRNKEzIwMTktMDMtMjkgMTU6NDI6MTEUDAsKB2N1c1R5cGUTSgIwMhQMCwoKZV9iaXpTZXJubxNKFENSRUwyMDE5MDMyOTAwMDIzNjY3FAwLCgpjcmVhdGVVc2VyE0oCMTMUDAsKC2xhc3RDaGdUaW1lE0oTMjAxOS0wOS0xMCAxOTozMzo1NxQMCwoEcGFnZRMoARQMCwoJYXBwbHlEYXRlE0oKMjAxOS0wNy0xNBQMDBMLCwoHZXZlbnRJZBNKCURlbW9FbnRlchQMCwoMcXVvdGFMaW1pQW10EyiNGRQMCwoFc2Vybm8TShRDUkVMMjAxOTAzMjkwMDAyMzY2NxQMCwoKYXBwbHlTdGF0ZRNKAzEwMRQMCwoFZW5kRHQTSgoyMDE5LTAzLTIyFAwLCgpsYXN0Q2hnVXNyE0oP5pil5aSp5p2l5LqG77yBFAwLCgVzdHJEdBNKCjIwMTktMDMtMDEUDAsKCXF1b3RhVHlwZRNKDOWuouaIt+mZkOminRQMCwoFdG90YWwTKBIUDAsKA3N0cxNKAjAwFAwLCgRzaXplEygKFAwLCgpjcmVhdGVUaW1lE0oTMjAxOS0wMy0yOSAxNTo0MjoxMRQMCwoHY3VzVHlwZRNKAjAyFAwLCgpjcmVhdGVVc2VyE0oCMTMUDAsKC2xhc3RDaGdUaW1lE0oTMjAxOS0wOS0xMCAxOTozMzo1NxQMCwoEcGFnZRMoARQMCwoJYXBwbHlEYXRlE0oKMjAxOS0wNy0xNBQMDBQbehBqYXZhLmxhbmcuU3RyaW5nGAIQAQtKCmVfYml6U2Vybm8MC0oKZ19iaXpTZXJubwwc");

    }

    /**
     * 页面任务结束
     *
     * @param vo
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/page/task/done", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<Boolean> finishCurrPageTask(@RequestBody PageSubmitRequestVO vo) throws Exception {
        boolean result = false;
        try {
            result = this.bizFlowEngine.executeTask(vo.getG_bizSerno(), vo.getE_bizSerno(),
                    vo.getEventId(), vo.getInstNodeId(), vo.getTaskId(), vo.getData());
        } catch (Exception e) {
            logger.error("实例化事件ID：" + vo.getE_bizSerno() + "页面信息提交执行任务出现异常!");
        }
        return getResponseData(result);
    }

    /**
     * 任务认领
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/task/claim", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<String> taskClaim(@RequestBody InstFlowProcessVO VO) throws Exception {
        UserInfo userInfo = this.getUserInfo();
        String respCode = "0";
        if (Objects.nonNull(userInfo.getUserDutys()) && !userInfo.getUserDutys().isEmpty()) {
            List<String> dutyCodes = new ArrayList<>(userInfo.getUserDutys().size());
            userInfo.getUserDutys().forEach(s -> dutyCodes.add(s.getDutyCode()));
            List<String> nodes = this.instFlowProcessService.queryCanClaimNodes(userInfo.getUserId(), dutyCodes);
            if (Objects.nonNull(nodes) && !nodes.isEmpty()) {
                AprvUserVO vo = new AprvUserVO();
                vo.setUserId(userInfo.getUserId());
                vo.setUserName(userInfo.getUserName());
                vo.setOrgId(userInfo.getOrgInfo().getOrgCode());
                vo.setOrgName(userInfo.getOrgInfo().getOrgName());
                vo.setLegalOrgId(userInfo.getLegalOrg().getOrgCode());
                Integer rtl = this.instFlowProcessService.taskClaim(nodes, vo,VO.getBizSerno());
                if (Objects.nonNull(rtl) && rtl.intValue() > 0) {
                    respCode = "1";
                } else {
                    respCode = "-1";
                }
            } else {
                respCode = "-1";
            }
        }
        return getResponseData(respCode);
    }

    /**
     * 任务调单：分配任务人
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/task/changeUser", method = RequestMethod.GET)
    public @ResponseBody
    ResponseData<String> changeUser(@RequestParam(value = "nodeId", required = true) String nodeId, @RequestParam(value = "userId", required = true) String userId, @RequestParam(value = "userName", required = true) String userName) throws Exception {
        UserInfo userInfo = this.getUserInfo();
        String respCode = "0";
        InstFlowProcessVO instFlowProcessVO = instFlowProcessService.queryByNodeInstanceId(nodeId);
        instFlowProcessVO.setProcessUserId(userId);
        instFlowProcessVO.setProcessUserName(userName);
        //获取调单对象用户的机构信息
        VwUserDutyVO cond = new VwUserDutyVO();
        cond.setUserCode(userId);
        List<VwUserDutyVO> rs = vwUserDutyService.queryUserOrgInfo(cond);
        instFlowProcessVO.setProcessOrgId(rs.get(0).getOrgCode());
        instFlowProcessVO.setProcessOrgName(rs.get(0).getOrgName());
        Integer rtl = instFlowProcessService.updateAprvUserInfoByNodeInstId(instFlowProcessVO);
        if (Objects.nonNull(rtl) && rtl.intValue() > 0) {
            respCode = "1";
        } else {
            respCode = "-1";
        }
        return getResponseData(respCode);
    }


    /**
     * 获取pluginVo对象
     *
     * @param evo
     * @return
     * @throws Exception
     */

    protected EngineVO getPluginVoInfos(String bizSerno, String key, Object object) throws Exception {
        EngineVO evo = new EngineVO();
        evo.setBizSerno(bizSerno);
        InstFlowParamVO queryParam = new InstFlowParamVO();
        queryParam.setBizSerno(bizSerno);
        InstFlowParamVO param = instFlowParamService.queryContent(queryParam);
        if (Objects.nonNull(param) && StringUtil.isNotEmpty(param.getBizParamContent())) {
            String serializeStr = param.getBizParamContent();
            try {
                PluginVO vo = EngineUtil.deserializePluginVo(serializeStr);
                evo.getPluginVo().putPluginVO(vo);
                evo.getPluginVo().remove(key);
                evo.getPluginVo().addVOs(key, object);
            } catch (Exception e) {
                logger.error("当前节点实例:" + evo.getNodeInstanceId() + ", 待执行任务为：" + evo.getTaskId() + ", 上下文数据信息提取出现异常!", e);
                throw new FlowException("当前节点实例:" + evo.getNodeInstanceId() + ", 待执行任务为：" + evo.getTaskId() + ", 上下文数据信息提取出现异常!", e);
            }
        }
        logger.info("当前节点实例:" + evo.getNodeInstanceId() + ", 待执行任务为：" + evo.getTaskId() + ", 上下文数据信息提取结束......");
        return evo;
    }

    /**
     * 保存pluginvo信息
     *
     * @param evo
     * @return
     * @throws Exception
     */
    protected int savePluginVoInfos(EngineVO evo) throws Exception {
        logger.error("当前节点ID:" + evo.getNodeId() + ", 实例化流水:" + evo.getNodeInstanceId() + "序列化并保存相关参数信息开始......");
        String serializeStr = null;
        try {
            serializeStr = EngineUtil.serializePluginVo(evo.getPluginVo());
        } catch (Exception e) {
            logger.error("当前节点ID:" + evo.getNodeId() + ", 实例化流水:" + evo.getNodeInstanceId() + "序列化相关参数异常!", e);
            throw new FlowException("当前节点ID:" + evo.getNodeId() + ", 实例化流水:" + evo.getNodeInstanceId() + "序列化相关参数异常!", e);
        }

        InstFlowParamVO param = new InstFlowParamVO();
        param.setBizSerno(evo.getBizSerno());

        //先删除在新增
        instFlowParamService.deleteByPk(param);
        param.setInstNodeId(evo.getNodeInstanceId());
        param.setTaskId(evo.getTaskId());
        param.setBizParamContent(serializeStr);
        int record = instFlowParamService.insertInstFlowParam(param);
        logger.info("当前节点ID:" + evo.getNodeId() + ", 实例化流水:" + evo.getNodeInstanceId() + "序列化并保存相关参数信息结束......");
        return record;
    }

    /**
     * 调单相关信息获取
     *
     * @param
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/userDuty/infos", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<List<VwUserDutyVO>> queryUserDutyInfos(@RequestBody VwUserDutyVO vwUserDutyVO) {
        setUserInfoToVO(vwUserDutyVO);
        List<String> list = new ArrayList<>();
        if (!StringUtil.isNullorBank(vwUserDutyVO.getDutyCode())) {
            list = Arrays.asList(vwUserDutyVO.getDutyCode().split("','")).stream().map(s->(s.trim())).collect(Collectors.toList());
            vwUserDutyVO.setDutyCodes(list);
        }
        List<VwUserDutyVO> outputVo = vwUserDutyService.queryAllOwner(vwUserDutyVO);
        //给处理数赋值
        outputVo.forEach(item -> {
            String userCode = item.getUserCode();
            int tasksNum = instFlowProcessService.countTasksNum(userCode);
            item.setTaskNum(tasksNum);
        });
        return getResponseData(outputVo);
    }

    /**
     * 根据流水号查询历史审批信息
     * @author xiezw
     * @params  * @param null
     * @return
     * @date 2020/2/27 9:52
     * @version 0.1
     */
    @RequestMapping(value = "/flow/history", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<List<InstFlowHistoryVO>> queryAprvHisByBiz(@RequestBody InstFlowHistoryVO instFlowHistoryVO) {
        setUserInfoToVO(instFlowHistoryVO);
        List<InstFlowHistoryVO> outputVo = instFlowHistoryService.queryByBizSerno(instFlowHistoryVO);
        return getResponseData(outputVo);
    }

    /**
     * 插入信息到历史审批信息表
     * @author xiezw
     * @params  * @param null
     * @return
     * @date 2020/2/27 14:54
     * @version 0.1
     */
    @RequestMapping(value = "/flow/history/save", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<Integer> insertAprvHisByBiz(@RequestBody PageSubmitRequestVO requestVo) {
        InstFlowHistoryVO instFlowHistoryVO = new InstFlowHistoryVO();
        instFlowHistoryVO.setBizSerno(requestVo.getE_bizSerno());
        // 根据节点实力编号查询阶段名称
        String stageName = instFlowProcessService.queryStageByInstNodeId(requestVo.getInstNodeId());
        instFlowHistoryVO.setFlowStage(stageName);

        Map<String, Object> stringObjectMap = requestVo.getData().get(0);
        String aprvOpinion = (String) stringObjectMap.get("aprvOpinion");
        String aprvComment = (String) stringObjectMap.get("aprvComment");
        String aprvUserId = (String) stringObjectMap.get("aprvUserId");

        instFlowHistoryVO.setAprvStatus(aprvOpinion);
        instFlowHistoryVO.setAprvComment(aprvComment);
        instFlowHistoryVO.setAprvUserCode(aprvUserId);
        instFlowHistoryVO.setAprvDate(TimeUtil.getCurrentDateTime());
        int outputVo = instFlowHistoryService.insertInstFlowHistory(instFlowHistoryVO);
        return getResponseData(outputVo);
    }
}
